#include "Solver.h"

using namespace std;

Solver :: Solver(Configurator* configurator)
{
	dwarfConfigurator = configurator;					// process settings from the command line 
	dwarfConfigurator -> WriteSettings();
	dwarfConfigurator -> GetContent(&mainContent, &contentSize, &patternContent, &stateDimensionCoincidence);
}

void Solver::ConstructStates()
{
	states = (int**) malloc (sizeof(int*)*stateDimensionChars);				// new states array
	for (int i = 0; i < stateDimensionChars; i++)
	{
		states[i] = (int*) malloc (sizeof(int)*(stateDimensionCoincidence + 1));
	}

	for (int i = 0; i < stateDimensionCoincidence + 1; i++)
	{
		for (int j = 0; j < stateDimensionChars; j++)
		{
			states[j] [i] = 0;
		}
    }
    for (int i = 0; i < stateDimensionCoincidence; i++)
	{
		states[patternContent[0]] [i] = 1;				// all turns from any char to the the first char in pattern are "initial" (=1)
    }
	for (int i = 1; i < stateDimensionCoincidence; i++)
    {
		int currentState = states[patternContent[i]] [i];
        if (currentState > 0)							// cycle-in-pattern checker
        {
			states[patternContent[currentState]] [i + 1] = currentState + 1;    // if cycle found, add "cycle" state
        }
 		states[patternContent[i]] [i] = i + 1;			// all turns from i-char to the (i+1)-char are "next" (equals to i+1)
    } 
	free(patternContent);								// pattern won't be used later
}

void Solver::StatesProcessing()
{
	int state = 0;
	for (int i = 0; i < contentSize; i++)
	{
		if (mainContent[i] > 0)
		{
			state = states[mainContent[i]][state];				// change the state 
		}
        if (state == stateDimensionCoincidence)					// pattern found!
        {
			positions.push_back(i);								// push to list
            state = 0;
        }
	}
}

void Solver::Solve()
{
	ConstructStates();								// construct the array of states
	StatesProcessing();							    // traverse the mainContent using states array
	free(mainContent);
}

void Solver::Finish(double time)		// Problem results output
{
	if (! positions.empty())
	{
		printf("\n\nTotal count of pattern entries: %d \n", positions.size());
	}
	else
	{
		printf("\n\nPattern not found        \n");
	}
	dwarfConfigurator -> Close(time, positions);
}